#include "stdafx.h"
#include "XEditImpl.h"

#include "Util.h"
#include "UIUtil.h"

#include "IntSkinImpl.h"
#include "XBSTR.h"

template <class I>
CXEditImpl<I>::CXEditImpl()
{
    ModifyStyle(WS_TABSTOP | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
    m_bShowHintText = FALSE;
    m_clrHintText = RGB(0xE8, 0xE8, 0xE8);
}

template <class I>
CXEditImpl<I>::~CXEditImpl()
{
}

//////////////////////////////////////////////////////////////////////////
// IXEdit
template <class I>
DWORD CXEditImpl<I>::get_MaxCount()
{
    if(m_xRealWnd == NULL)
        return -1;
    else
        return ::SendMessage((HWND)m_xRealWnd, EM_GETLIMITTEXT, 0, 0);
}

template <class I>
void CXEditImpl<I>::put_MaxCount(IN DWORD dwCount)
{
    if(m_xRealWnd != NULL)
        ::SendMessage((HWND)m_xRealWnd, EM_LIMITTEXT, dwCount, 0);
}

template <class I>
BOOL CXEditImpl<I>::get_ReadOnly()
{
    if(m_xRealWnd == NULL)
        return FALSE;
    else
        return ((::GetWindowLongPtr((HWND)m_xRealWnd, GWL_STYLE) & ES_READONLY) == ES_READONLY);
}

template <class I>
void CXEditImpl<I>::put_ReadOnly(IN BOOL bReadOnly)
{
    if(m_xRealWnd != NULL)
        ::SendMessage((HWND)m_xRealWnd, EM_SETREADONLY, (WPARAM)bReadOnly, 0);
}

template <class I>
HRESULT CXEditImpl<I>::get_HintText(OUT BSTR* pbstrHint)
{
    if(::SysReAllocString(pbstrHint, m_strHintText.GetData()))
        return S_OK;
    else
        return E_FAIL;
}

template <class I>
void CXEditImpl<I>::put_HintText(IN LPCTSTR szHint)
{
    if(szHint == NULL)
        szHint = _T("");
    if(m_strHintText != szHint)
    {
        IntSkinImpl::SetorLoadStringSaveResId(szHint, m_strHintText, m_strHintTextResId);
        ShowHintText();
    }
}

template <class I>
COLORREF CXEditImpl<I>::get_HintTextColor()
{
    return m_clrHintText;
}

template <class I>
void CXEditImpl<I>::put_HintTextColor(IN COLORREF clrHint)
{
    if(m_clrHintText != clrHint)
    {
        m_clrHintText = clrHint;
        ShowHintText();
    }
}

template <class I>
BOOL CXEditImpl<I>::get_Multiline()
{
    return ((GetStyle() & ES_MULTILINE) == ES_MULTILINE);
}

template <class I>
void CXEditImpl<I>::put_Multiline(IN BOOL bMultiline)
{
    ModifyStyle(ES_MULTILINE | ES_WANTRETURN | WS_VSCROLL, 0);
}

template <class I>
BOOL CXEditImpl<I>::get_AutoHScroll()
{
    return ((GetStyle() & ES_AUTOHSCROLL) == ES_AUTOHSCROLL);
}

template <class I>
void CXEditImpl<I>::put_AutoHScroll(IN BOOL bAutoScroll)
{
    ModifyStyle(ES_AUTOHSCROLL, 0);
}

template <class I>
BOOL CXEditImpl<I>::get_AutoVScroll()
{
    return ((GetStyle() & ES_AUTOVSCROLL) == ES_AUTOVSCROLL);
}

template <class I>
void CXEditImpl<I>::put_AutoVScroll(IN BOOL bAutoScroll)
{
    ModifyStyle(ES_AUTOVSCROLL, 0);
}

//////////////////////////////////////////////////////////////////////////
// IXBaseObj
template <class I>
void CXEditImpl<I>::OnFinalRelease()
{
    superclass::OnFinalRelease();
}

//////////////////////////////////////////////////////////////////////////
// CXEditImpl
template <class I>
void CXEditImpl<I>::HideHintText()
{
    m_bShowHintText = FALSE;
    if(m_xRealWnd != NULL)
        ::SetWindowText((HWND)m_xRealWnd, _T(""));
}

template <class I>
void CXEditImpl<I>::ShowHintText()
{
    if(m_xRealWnd != NULL)
    {
        if(::GetWindowTextLength((HWND)m_xRealWnd) == 0)
        {
            ::SetWindowText((HWND)m_xRealWnd, m_strHintText.c_str());
            m_bShowHintText = TRUE;
        }
    }
}

//////////////////////////////////////////////////////////////////////////
// CXHwndImpl Callback
template <class I>
XString CXEditImpl<I>::GetHwndClassName()
{
    return XString(WC_EDIT);
}

// CXControlImpl
template <class I>
HRESULT CXEditImpl<I>::OnSkinLangChanged()
{
    superclass::OnSkinLangChanged();
    XString strHintText;
    XString strHintTextResId = m_strHintTextResId;
    if(IntSkinImpl::ReLoadString(m_strHintTextResId.c_str(), strHintText))
    {
        put_HintText(strHintText.c_str());
        m_strHintTextResId = strHintTextResId;
    }
    return S_OK;
}
//////////////////////////////////////////////////////////////////////////

template <class I>
DWORD CXEditImpl<I>::GetHwndFlags()
{
    return XHwnd_NeedCommand | XHwnd_TextColor;
}

template <class I>
BOOL CXEditImpl<I>::OnCommand(UINT command)
{
    LPCTSTR szEvt = NULL;
    if(command == EN_CHANGE)
        szEvt = EditEvent_Change;
    else if(command == EN_KILLFOCUS)
        szEvt = EditEvent_KillFocus;
    else if(command == EN_SETFOCUS)
        szEvt = EditEvent_SetFocus;
    else if(command == EN_UPDATE)
        szEvt = EditEvent_Update;

    if(!m_strHintText.empty())
    {
        if(szEvt == EditEvent_SetFocus)
        {
            XBSTR bstrText;
            if(SUCCEEDED(superclass::get_Text(&bstrText)))
            {
                if(bstrText == m_strHintText.c_str())
                {
                    HideHintText();
                }
            }
        }
        else if(szEvt == EditEvent_KillFocus)
        {
            ShowHintText();
        }
        else if(szEvt == EditEvent_Update)
        {
            XBSTR bstrText;
            if(SUCCEEDED(superclass::get_Text(&bstrText)))
            {
                m_bShowHintText = (bstrText == m_strHintText.c_str());
            }
        }
    }

    if(szEvt != NULL)
    {
        InvokeEventHandler(this, szEvt, (LPARAM)m_xRealWnd);
        return TRUE;
    }

    return FALSE;
}

template <class I>
BOOL CXEditImpl<I>::OnCtlColor(XCANVAS xCanvas, OUT XBRUSH* pBrush)
{
    COLORREF clrText = m_clrHintText;
    if(!m_bShowHintText)
    {
        clrText = UIUtil::XGetTextEnv(this)->get_TextColor();
    }
    ::SetTextColor((HDC)xCanvas, clrText);

    if(m_BkBrush != NULL)
    {
        LOGBRUSH LogBrush = {0};
        ::GetObject((HANDLE)m_BkBrush, sizeof(LogBrush), &LogBrush);
        if(BS_SOLID == LogBrush.lbStyle)
            ::SetBkColor((HDC)xCanvas, LogBrush.lbColor);
    }

    *pBrush = m_BkBrush;
    return (m_BkBrush != NULL);
}

template <class I>
HRESULT CXEditImpl<I>::get_Text(IN BSTR* bstrText)
{
    HRESULT hResult = superclass::get_Text(bstrText);
    if(SUCCEEDED(hResult))
    {
        if(m_strHintText == *bstrText)
        {
            TCHAR szTemp[2] = {0};
            if(::SysReAllocString(bstrText, szTemp))
                hResult = S_OK;
            else
                hResult = E_FAIL;
        }
    }
    return hResult;
}
